module per_mod
   implicit none
   private
   public::per
contains
   function binary(k,n)result(f1)
      integer,intent(in)::k,n
      integer::f1(0:n),i
      f1=0
      do i=0,n-1
         f1(i)=merge(1,0,btest(k,i))
      end do
      f1(n)=sum(f1(0:n-1))
   end function binary

   real(8) function per(a) result(f1)
      real(8),intent(in)::a(0:,0:)
      integer::chi(0:size(a,dim=1))
      real(8)::rowsumprod,rowsum
      integer::c,k,m,p,n
      n=size(a,dim=1)
      c=2**n
      f1=0.d0
      do k=1,c-1
         rowsumprod=1
         chi=binary(k, n)
         !chi=graycode(k, n)
         do m=0,n-1
            rowsum=0.d0
            do p=0,n-1
               rowsum=rowsum+chi(p)*a(m,p)
            end do
            rowsumprod=rowsumprod*rowsum
            !if(abs(rowsumprod)<epsilon(1.d0))exit
         end do
         f1=f1+(-1)**(n-chi(n))*rowsumprod
      end do
   end function per

   function graycode(k,n) result(f1)
      integer::f1(0:n)
      integer,intent(in)::k,n
      integer::i,res
      res=ieor(k/2, k)
      f1=0
      do i=0,n-1
         f1(i)=merge(1,0,btest(res,i))
      end do
      f1(n)=sum(f1(0:n-1))
   end function graycode
end module per_mod

program main
   use per_mod
   implicit none
   integer,parameter::n=3
   real(8)::a(0:n-1,0:n-1)
   a=reshape(&
      &[-4,-5,-6,&
      &  1, 2, 3,&
      &  7, 8, 9],[3,3])
   write(*,*)per(a)
end program main
